﻿using Microsoft.SharePoint.Client;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security;
using System.Threading.Tasks;

namespace SPIE.Console
{
    class Program
    {
        static void Main(string[] args)
        {
            UserCredentials credentials = new UserCredentials(@"user", "password", CredentialsType.SharePointOnline);

            ClientContext context = new ClientContext("<my sharepoint site>");
            ListItemCollection coll = GetItemCollection(context, credentials);

            DownloadDocuments(context, coll, @"C:\temp");

        }

        private static ListItemCollection GetItemCollection(ClientContext context, UserCredentials credentials)
        {
            context.Credentials = credentials.GetCredentials();

            Web web = context.Web;
            List docs = web.Lists.GetByTitle("Documents");
            context.Load(docs, list => list.RootFolder.ServerRelativeUrl);

            ListItemCollection coll = docs.GetItems(CamlQuery.CreateAllItemsQuery());
            context.Load(coll, items => items.Include
                                            (item => item.FileSystemObjectType,
                                             item => item.Folder,
                                             item => item["FileRef"],
                                             item => item.ParentList.RootFolder.ServerRelativeUrl));
            context.ExecuteQuery();
            return coll;
        }
        private static void CopyStream(Stream source, Stream destination)
        {
            byte[] buffer = new byte[32768];
            int bytesRead;
            do
            {
                bytesRead = source.Read(buffer, 0, buffer.Length);
                destination.Write(buffer, 0, bytesRead);
            } while (bytesRead != 0);
        }
        private static void DownloadDocuments(ClientContext context, ListItemCollection itemsCollection, string localDestinationPath, bool verbose = true)
        {
            if (verbose)
                System.Console.WriteLine("Downloading {0} documents started", itemsCollection.Count());


            if (itemsCollection.Count > 0)
            {
                foreach (var item in itemsCollection)
                {
                    var folder = item.Folder;
                    var itemPath = GetListItemPath(item);
                    string fullItemPath = Path.Combine(localDestinationPath, itemPath);
                    if (verbose)
                        System.Console.WriteLine("{0} -> {1}", itemPath, localDestinationPath);
                    if (item.FileSystemObjectType == FileSystemObjectType.Folder)
                    {
                        if (!Directory.Exists(fullItemPath))
                        {
                            Directory.CreateDirectory(fullItemPath);
                        }
                    }
                    else if (item.FileSystemObjectType == FileSystemObjectType.File)
                    {

                        try
                        {
                            FileInformation fileInformation = Microsoft.SharePoint.Client.File.OpenBinaryDirect(context, (string)item["FileRef"]);

                            using (MemoryStream memoryStream = new MemoryStream())
                            {
                                using (Stream file = System.IO.File.OpenWrite(fullItemPath))
                                {
                                    CopyStream(fileInformation.Stream, file);
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            if (verbose)
                                System.Console.WriteLine("Error {0} = ", ex.Message);
                        }

                    }
                }
            }
        }
        private static string GetListItemPath(ListItem item)
        {

            string filePath = (string)item["FileRef"];
            string rootFolderPath = item.ParentList.RootFolder.ServerRelativeUrl;
            if (filePath.StartsWith(rootFolderPath))
            {
                filePath = filePath.Substring(rootFolderPath.Length);
            }
            if (filePath.StartsWith(@"\") || filePath.StartsWith(@"/"))
                filePath = filePath.Remove(0, 1);

            return filePath;
        }
      
    }
}

